/* Nate Deisinger (ndeisinger@wisc.edu)
 *
 * This file is part of soot-csi, a project to apply lightweight
 * instrumentation to Java programs to facilitate debugging through
 * the Soot analysis framework.
 *
 * Copyright (c) 2014, Nate Deisinger, University of Wisconsin-Madison
 *   Madison, Wisconsin 53715
 *   All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor,
 *   Boston, MA  02110-1301
 *   USA
 * or retrieve version 2.1 at their website:
 *   http://www.gnu.org/licenses/lgpl-2.1.html
 */
package uwmadison.jpdg;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.google.gson.Gson;

import soot.Value;
/**
 * A partial implementation of an extension to the JavaPDG project to
 * allow for exporting graphs in a GraphML-friendly format.
 * 
 * Requires the JPDG classes to build.  (https://github.com/timtadh/jpdg)
 * @author Nate Deisinger
 */
public class ExtendedDataNode extends Node {

    static HashMap<String, Integer> funcMap = new HashMap<String, Integer>();
    public static HashMap<Integer, String> IDMap = new HashMap<Integer, String>();
    static int funcId = 0;

    public ExtendedDataNode(int id, int label, String extra,
            String package_name, String class_name, String method_name,
            String type, int start_line, int start_column, int end_line,
            int end_column, Graph g) {
        super(id, label, extra, package_name, class_name, method_name, type,
                start_line, start_column, end_line, end_column, g);
    }

    public String Serialize()
    {
        return super.Serialize();
    }

    public int getFuncID(String s)
    {
        if (!funcMap.containsKey(s))
        {
            funcMap.put(s, --funcId);
        }
        return funcMap.get(s);
    }

    public String dataSerialize(Set<String> mustDef, Set<String> mayDef, Set<String> mayUse)
    {
        Map<String,Object> M = new LinkedHashMap<String,Object>();
        String id_string = "n:" + getFuncID(package_name + class_name + method_name) + ":" + id;
        String qualified_name = package_name + '.' + class_name + '.' + method_name;
        IDMap.put(id, id_string);
        M.put("id", id_string);
        //M.put("label", g.label(id));
        //M.put("extra", extra);

        M.put("label", type.equals("entry") ? "entry: " + qualified_name : extra);
        //M.put("kind", "expression");
        M.put("package_name", package_name);
        M.put("class_name", class_name);
        M.put("method_name", method_name);
        M.put("kind", type.equals("entry") ? "entry" : "expression");
        M.put("procedure", qualified_name);
        /*M.put("kind", type.equals("call") ? "call-site" : "expression");
        if (type.equals("call"))
        {
            M.put("call-name", "");
        }*/
        StringBuilder lineBuilder = new StringBuilder();
        lineBuilder.append("(");
        if(start_line > end_line)
        {
            int temp = start_line;
            start_line = end_line;
            end_line = temp;
            if (start_line == -1) start_line = end_line;
        }
        for (int i = start_line; i <= end_line; i++)
        {
            lineBuilder.append(i + " ");
        }
        if (lineBuilder.length() > 1) lineBuilder.deleteCharAt(lineBuilder.length() - 1);
        lineBuilder.append(")");
        M.put("lines", lineBuilder.toString());

        //Add definitions/uses
        StringBuilder multiBuilder = new StringBuilder();
        if (mayUse.size() > 0)
        {
            multiBuilder = new StringBuilder();
            for (String s : mayUse)
            {
                multiBuilder.append(s + ' ');
            }
            M.put("alocs-used", multiBuilder.toString());
        }
        if (mustDef.size() > 0)
        {
            multiBuilder = new StringBuilder();
            for (String s : mustDef)
            {
                multiBuilder.append(s + ' ');
            }
            M.put("alocs-defd", multiBuilder.toString());
        }

        if (mayDef.size() > 0)
        {
            multiBuilder = new StringBuilder();
            for (String s : mayDef)
            {
                multiBuilder.append(s + ' ');
            }
            M.put("alocs-maydef", multiBuilder.toString());
        }
        return "vertex\t" + (new Gson()).toJson(M);
    }

}
